package cn.spdb.harrier.rpc.remote;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.spdb.harrier.rpc.common.RpcRequest;
import cn.spdb.harrier.rpc.common.RpcResponse;
import cn.spdb.harrier.rpc.common.ThreadPoolManager;
import cn.spdb.harrier.rpc.protocol.ProtocolEventType;
import cn.spdb.harrier.rpc.protocol.RpcProtocol;
import cn.spdb.harrier.rpc.transport.RpcServiceTransportBean;
import cn.spdb.harrier.rpc.transport.http.HttpServiceTransportBean;
import cn.spdb.harrier.rpc.transport.http.InterfaceHttpHandler;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.timeout.IdleStateEvent;

public class NettyServerHandler extends ChannelDuplexHandler {

	private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		logger.debug("channel close :" + ctx.channel().remoteAddress().toString());
		ctx.channel().close();
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		logger.debug("client connect success  :" + ctx.channel().remoteAddress().toString());
	}

/**
 * 当通道读取到消息时触发的方法，用于处理不同类型的请求消息：
 * - HTTP 请求
 * - WebSocket 消息
 * - 自定义 RPC 协议消息
 *
 * @param ctx Netty 的 ChannelHandlerContext，用于上下文操作
 * @param msg 接收到的消息对象
 * @throws Exception 异常信息
 */
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    // 如果是 HTTP 请求
    if (msg instanceof FullHttpRequest) {
        FullHttpRequest httpRequest = (FullHttpRequest) msg;
        // 提交到线程池中异步执行 HTTP 请求处理
        ThreadPoolManager.getInstance().addExecute(() -> readHttpHandler(ctx, httpRequest));

    // 如果是 WebSocket 消息
    } else if (msg instanceof WebSocketFrame) {
        WebSocketFrame webSocketFrame = (WebSocketFrame) msg;
        // 提交到线程池中异步处理 WebSocket 消息（当前为空实现）
        ThreadPoolManager.getInstance().addExecute(() -> readWebSocketHandler(ctx, webSocketFrame));

    // 如果是自定义 RPC 协议消息
    } else if (msg instanceof RpcProtocol<?>) {
        RpcProtocol<Object> rpcProtocol = (RpcProtocol<Object>) msg;

        // 如果是心跳事件，记录日志并返回，不作进一步处理
        if (rpcProtocol.getProtocolHeader().getEventType() == ProtocolEventType.HEARTBEAT.getType()) {
            logger.debug(ProtocolEventType.HEARTBEAT.getDescription() + ":" + ctx.channel().remoteAddress().toString());
            return;
        }

        // 如果是压缩错误事件，记录日志并返回
        if (rpcProtocol.getProtocolHeader().getEventType() == ProtocolEventType.COMPERESS_ERROR.getType()) {
            logger.debug(ProtocolEventType.COMPERESS_ERROR.getDescription() + ":" + ctx.channel().remoteAddress().toString());
            return;
        }

        // 提交到线程池中异步处理 RPC 请求
        ThreadPoolManager.getInstance().addExecute(() -> readRpcHandler(ctx, rpcProtocol));

    // 其他未知类型的消息，直接写回客户端
    } else {
        ctx.writeAndFlush(msg);
        return;
    }
}


	private void readWebSocketHandler(ChannelHandlerContext ctx, WebSocketFrame webSocketFrame) {

	}

/**
 * 处理接收到的 RPC 请求协议消息，执行对应的服务方法，并返回响应结果
 *
 * @param ctx Netty 的 ChannelHandlerContext 对象，用于与客户端通信
 * @param rpcProtocol 接收到的 RPC 协议消息，包含请求头和请求体
 */
private void readRpcHandler(ChannelHandlerContext ctx, RpcProtocol<Object> rpcProtocol) {
    // 创建一个空的 RPC 响应对象
    RpcResponse response = new RpcResponse();

    // 从协议中提取出请求对象
    RpcRequest request = (RpcRequest) rpcProtocol.getBody();

    // 设置响应状态为成功（默认）
    response.setStatus((byte) 0);

    // 获取请求中的类名、方法名、参数类型和参数值
    String className = request.getClassName();
    String methodName = request.getMethodName();
    Class<?>[] parameterTypes = request.getParameterTypes();
    Object[] arguments = request.getParameters();

    Object result = null;
    try {
        // 调用 RpcServiceTransportBean 执行实际的方法并获取结果
        result = RpcServiceTransportBean.invoke(className, methodName, parameterTypes, arguments);
    } catch (Exception e) {
        // 如果调用过程中发生异常，设置响应状态为失败，并记录错误日志
        response.setStatus((byte) -1);
        logger.error("netty server execute error, service name:{} method name:{}", className + methodName, e);
    }

    // 将执行结果设置到响应对象中
    response.setResult(result);

    // 更新协议体为响应对象
    rpcProtocol.setBody(response);

    // 设置协议头中的事件类型为响应类型
    rpcProtocol.getProtocolHeader().setEventType(ProtocolEventType.RESPONSE.getType());

    // 记录警告级别的日志，显示当前响应的请求 ID
    logger.warn("server:" + rpcProtocol.getProtocolHeader().getRequestId());

    // 向客户端发送响应协议消息
    ctx.writeAndFlush(rpcProtocol);
}


	private void readHttpHandler(ChannelHandlerContext ctx, FullHttpRequest httpRequest) {
		String uri = httpRequest.uri();// 路径
		QueryStringDecoder decoder = new QueryStringDecoder(uri);
		String path = decoder.path();
		InterfaceHttpHandler handler = HttpServiceTransportBean.getHttpHandler(path);
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
		if (handler != null) {
			response = handler.handler(httpRequest);
		}
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof IdleStateEvent) {
			logger.debug("IdleStateEvent triggered send channel " + ctx.channel());
		} else {
			super.userEventTriggered(ctx, evt);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		logger.error("exceptionCaught :{}", cause.getMessage(), cause);
		ctx.channel().close();
	}
}
